Program 			-> inicio Block fim

Block 				-> Block2 Block | Epsilon
Block2 				-> Declarations | Stmt_List

Declarations 		-> Declarations2 Declarations | Epsilon
Declarations2 		-> VarDecl | SubprogDecl | TypeDecl

VarDecl 			-> Type ":" Id_List";" VarDecl | Epsilon
Type 				-> Standard_Type | vetor "[" NUM ":" NUM "]" Standard_Type
Standard_Type 		-> inteiro | real | char | logico | ID VerificaDecl

VerificaDecl 		-> ":" Id_List ";" VarDecl | Name2 "<-" Expression Stmt_List1 | "(" Proc_Stmt_MenosID2 Stmt_List1 | Epsilon 

SubprogDecl 		-> Subprog inicio Block fim
Subprog 			-> funcao ID Arguments ":" Standard_type ";" | procedimento ID Arguments ";"
Arguments 			-> "(" Id_List ")" | Epsilon

Id_List 			-> ID Id_List2
Id_List2 			-> "," ID Id_List2 | Epsilon

TypeDecl 			-> tipo ID = registro VarDecl fimregistro";"

Stmt_List 			-> Statement Stmt_List1
Stmt_List1 			-> ";" Stmt_List2 | Epsilon
Stmt_List2 			-> Stmt_List | Epsilon

Opcao_Stmt 			-> inicio Stmt_List fim | Statement

Se_Stmt				-> se Expression entao Senao_Stmt | Opcao_Stmt 
Senao_Stmt			-> Se_Stmt fimse | senao Se_Stmt fimse

Statement 			->  ID VerificaDecl |
						Se_Stmt         |
						enquanto Expression faca Opcao_Stmt fimenquanto |
						seletor Expression inicio CaseBlock fimseletor |
						leia "(" Expr_List ")" |
						imprima "(" Expr_list ")" |
						quebrar

CaseBlock 			-> caso Expression ":" Stmt_List CaseBlock | padrao ":" Stmt_List CaseBlock | Epsilon

Proc_Stmt_MenosID2	-> ")" | Expression ")"

Expr_List 			-> Expression Expr_list2
Expr_list2 			-> "," Expression Expr_List2 | Epsilon

Expression 			-> BinOpE BinOpOuOp
BinOpOuOp 			-> ou BinOpE BinOpOuOp | Epsilon

BinOpE 				-> BinOpIgualDesigual BinOpEOp
BinOpEOp			-> e BinOpIgualDesigual BinOpEOp | Esilon

BinOpIgualDesigual 	-> BinOpRel BinOpIgualDesigualOp
BinOpIgualDesigualOp -> IgualDesigualOp BinOpRel | Epsilon
IgualDesigualOp 	-> "=" | "<>"

BinOpRel 			-> BinOpAdSub BinOpRelOp
BinOpRelOp 			-> RelOp BinOpAdSub | Epsilon
RelOp 				-> "<" | ">" | "<=" | ">="

BinOpAdSub 			-> BinOpMultDiv BinOpAdSubOp
BinOpAdSubOp 		-> AdSubOp BinOpAdSub | Epsilon
AdSubOp 			-> "+" | "-"

BinOpMultDiv 		-> Primary BinOpMultDivOp
BinOpMultDivOp 		-> MultDivOp Primary BinOpMultDiv | Epsilon
MultDivOp 			-> "*" | "/"

Primary 			-> Name Primary2 | "(" Expression ")" | NUM | verdadeiro | falso | LITERAL | UnaryOp Primary
Primary2 			-> "(" Expr_List ")" | Epsilon

Name 				-> ID Name2
Name2 				-> "["Expression"]" Name3 | Name3
Name3 				-> "." Name | Epsilon

UnaryOp 			-> "+" | "-" | nao
